# backend/modules/authentication/routes.py

from flask_restful import Resource, reqparse  # 从 flask_restful 导入 Resource 和 reqparse
from flask import request, jsonify  # 从 flask 导入 request 和 jsonify
from flask_jwt_extended import (
    create_access_token, create_refresh_token,  # 导入生成访问令牌和刷新令牌的函数
    jwt_required, get_jwt_identity,  # 导入 JWT 相关的装饰器和函数
    set_access_cookies, set_refresh_cookies,  # 导入设置 cookies 的函数
)
from ...extensions import db  # 从 extensions 导入 db
from .models import User  # 从当前模块导入 User 模型

# 定义身份验证路由类
class AuthenticationRoutes:
    def __init__(self, api):
        # 初始化时注册各个资源到指定的 API 路径
        api.add_resource(Register, '/api/auth/register')  # 注册路由
        api.add_resource(Login, '/api/auth/login')  # 登录路由
        api.add_resource(RefreshToken, '/api/auth/refresh')  # 刷新令牌路由
        api.add_resource(UserList, '/api/auth/users')  # 用户列表路由
        api.add_resource(UserUpdate, '/api/auth/users/update/<string:username>')  # 更新用户信息路由
        api.add_resource(UserDelete, '/api/auth/users/delete/<string:username>')  # 删除用户路由
        api.add_resource(ChangePassword, '/api/auth/change_password')  # 修改密码路由，新增的路由

# 定义注册资源
class Register(Resource):
    @jwt_required()  # 需要 JWT 认证
    def post(self):  # 处理 POST 请求
        # 获取当前用户身份信息
        current_identity = get_jwt_identity()
        # 根据当前身份用户名获取用户
        current_user = User.query.filter_by(username=current_identity['username']).first()

        if not current_user:  # 如果用户不存在
            return {"message": "用户身份验证失败"}, 401  # 返回身份验证失败的消息

        # 创建请求解析对象
        parser = reqparse.RequestParser()
        # 添加用户名、密码和角色参数
        parser.add_argument('username', required=True, help="Username is required")
        parser.add_argument('password', required=True, help="Password is required")
        parser.add_argument('role', required=True, help="Role is required")
        args = parser.parse_args()  # 解析参数

        # 检查用户名是否已经存在
        if User.query.filter_by(username=args['username']).first():
            return {"message": "用户名已存在"}, 409  # 返回用户名已存在的消息

        # 权限控制
        if args['role'] == '管理员':
            # 检查当前用户是否为 pzy
            if not current_user.is_pzy():
                return {"message": "只有 'pzy' 可以创建管理员"}, 403  # 返回权限不足的消息
        else:
            # 检查当前用户是否为管理员
            if current_user.role != '管理员':
                return {"message": "只有管理员可以创建普通用户"}, 403  # 返回权限不足的消息

        # 创建新用户实例
        new_user = User(username=args['username'], role=args['role'])
        # 设置新用户密码
        new_user.set_password(args['password'])
        # 将新用户添加到数据库会话
        db.session.add(new_user)
        # 提交当前会话
        db.session.commit()

        return {"message": "用户注册成功"}, 201  # 返回注册成功的消息

# 定义登录资源
class Login(Resource):
    def post(self):  # 处理 POST 请求
        # 创建请求解析对象
        parser = reqparse.RequestParser()
        # 添加用户名和密码参数
        parser.add_argument('username', required=True, help="Username is required")
        parser.add_argument('password', required=True, help="Password is required")
        args = parser.parse_args()  # 解析参数

        # 查询用户
        user = User.query.filter_by(username=args['username']).first()
        if not user or not user.check_password(args['password']):
            return {"message": "用户名或密码错误"}, 401  # 返回错误信息

        # 生成访问令牌和刷新令牌
        access_token = create_access_token(identity={"username": user.username, "role": user.role})
        refresh_token = create_refresh_token(identity={"username": user.username, "role": user.role})

        # 构造响应对象
        resp = jsonify({"login": True, "role": user.role})
        # 设置访问令牌的 cookie
        set_access_cookies(resp, access_token)
        # 设置刷新令牌的 cookie
        set_refresh_cookies(resp, refresh_token)
        # 设置 sessionStorage 需要前端处理，不在后端完成
        return resp  # 返回响应

# 定义刷新令牌资源
class RefreshToken(Resource):
    @jwt_required(refresh=True)  # 需要 JWT 认证并且需要刷新令牌
    def post(self):  # 处理 POST 请求
        # 获取当前身份
        current_identity = get_jwt_identity()
        # 生成新的访问令牌
        new_access_token = create_access_token(identity=current_identity)
        # 构造响应对象
        resp = jsonify({"access_token": new_access_token, "role": current_identity['role']})
        # 设置新的访问令牌的 cookie
        set_access_cookies(resp, new_access_token)
        return resp, 200  # 返回响应

# 定义用户列表资源
class UserList(Resource):
    @jwt_required()  # 需要 JWT 认证
    def get(self):  # 处理 GET 请求
        # 获取当前身份
        current_identity = get_jwt_identity()
        # 获取当前用户
        current_user = User.query.filter_by(username=current_identity['username']).first()

        if not current_user:  # 如果用户不存在
            return {"message": "用户身份验证失败"}, 401  # 返回身份验证失败的消息

        if current_user.role == '管理员':  # 如果当前用户是管理员
            # 获取所有用户
            users = User.query.all()
            user_list = [
                {"username": user.username, "role": user.role, "created_at": user.created_at.strftime('%Y-%m-%d %H:%M:%S')}
                for user in users  # 生成用户列表
            ]
            return {"users": user_list}, 200  # 返回用户列表
        else:  # 如果当前用户不是管理员
            # 获取当前用户信息
            user_info = {
                "username": current_user.username,
                "role": current_user.role,
                "created_at": current_user.created_at.strftime('%Y-%m-%d %H:%M:%S')
            }
            return {"users": [user_info]}, 200  # 返回只有当前用户的信息

# 定义更新用户资源
class UserUpdate(Resource):
    @jwt_required()  # 需要 JWT 认证
    def put(self, username):  # 处理 PUT 请求
        # 获取当前身份
        current_identity = get_jwt_identity()
        # 获取当前用户
        current_user = User.query.filter_by(username=current_identity['username']).first()

        if not current_user:  # 如果用户不存在
            return {"message": "用户身份验证失败"}, 401  # 返回身份验证失败的消息

        # 获取目标用户
        target_user = User.query.filter_by(username=username).first()
        if not target_user:  # 如果目标用户不存在
            return {"message": "用户不存在"}, 404  # 返回用户不存在的消息

        # 权限控制
        if current_user.role == '管理员':  # 如果当前用户是管理员
            if target_user.role == '管理员' and not current_user.is_pzy():  # 检查是否有权限编辑其他管理员
                return {"message": "您无权编辑其他管理员"}, 403  # 返回权限不足的消息
        else:  # 如果当前用户不是管理员
            if current_user.username != username:  # 检查当前用户是否是目标用户
                return {"message": "未授权访问"}, 403  # 返回未授权访问的消息

        # 创建请求解析对象
        parser = reqparse.RequestParser()
        # 添加密码和角色参数
        parser.add_argument('password', type=str, location='json')
        parser.add_argument('role', type=str, location='json')
        args = parser.parse_args()  # 解析参数

        if args['role']:  # 如果角色参数不为空
            if args['role'] == '管理员':  # 如果新的角色是管理员
                if not current_user.is_pzy():  # 检查当前用户是否为 pzy
                    return {"message": "只有 'pzy' 可以赋予管理员角色"}, 403  # 返回权限不足的消息
            if current_user.role == '管理员':  # 如果当前用户是管理员
                # 只有 'pzy' 可以修改用户角色
                if target_user.role == '管理员' and not current_user.is_pzy():  # 检查是否有权限修改其他管理员的角色
                    return {"message": "您无权修改其他管理员的角色"}, 403  # 返回权限不足的消息
            if current_user.role == '管理员' and args['role'] != '管理员':  # 允许管理员降级用户角色
                target_user.role = args['role']  # 降级角色
            elif current_user.role == '管理员' and args['role'] == '管理员':  # 如果角色变化为管理员
                if current_user.is_pzy():  # 检查当前用户是否为 pzy
                    target_user.role = args['role']  # 授予管理员角色
                else:
                    return {"message": "只有 'pzy' 可以赋予管理员角色"}, 403  # 返回权限不足的消息
            elif current_user.role != '管理员':  # 如果当前用户不是管理员
                # 普通用户不能修改角色
                return {"message": "普通用户无法修改角色"}, 403  # 返回权限不足的消息

        if args['password']:  # 如果密码参数不为空
            target_user.set_password(args['password'])  # 设置目标用户的新密码

        db.session.commit()  # 提交当前会话
        return {"message": "用户更新成功"}, 200  # 返回更新成功的消息

# 定义删除用户资源
class UserDelete(Resource):
    @jwt_required()  # 需要 JWT 认证
    def delete(self, username):  # 处理 DELETE 请求
        # 获取当前身份
        current_identity = get_jwt_identity()
        # 获取当前用户
        current_user = User.query.filter_by(username=current_identity['username']).first()

        if not current_user:  # 如果用户不存在
            return {"message": "用户身份验证失败"}, 401  # 返回身份验证失败的消息

        # 获取目标用户
        target_user = User.query.filter_by(username=username).first()
        if not target_user:  # 如果目标用户不存在
            return {"message": "用户不存在"}, 404  # 返回用户不存在的消息

        # 防止删除自身
        if current_user.username == username:  # 检查是否试图删除自己
            return {"message": "不能删除当前登录的用户"}, 400  # 返回错误消息

        # 权限控制
        if current_user.role == '管理员':  # 如果当前用户是管理员
            if target_user.role == '管理员' and not current_user.is_pzy():  # 检查是否有权限删除其他管理员
                return {"message": "您无权删除其他管理员"}, 403  # 返回权限不足的消息
        else:  # 如果当前用户不是管理员
            return {"message": "未授权访问"}, 403  # 返回未授权访问的消息

        # 从数据库会话中删除目标用户
        db.session.delete(target_user)
        db.session.commit()  # 提交当前会话
        return {"message": "用户删除成功"}, 200  # 返回删除成功的消息

# 定义修改密码资源
class ChangePassword(Resource):
    @jwt_required()  # 需要 JWT 认证
    def post(self):  # 处理 POST 请求
        # 获取当前身份
        current_identity = get_jwt_identity()
        # 获取当前用户
        current_user = User.query.filter_by(username=current_identity['username']).first()

        if not current_user:  # 如果用户不存在
            return {"message": "用户身份验证失败"}, 401  # 返回身份验证失败的消息

        # 创建请求解析对象
        parser = reqparse.RequestParser()
        # 添加新密码参数
        parser.add_argument('new_password', type=str, required=True, help="新密码是必需的")
        args = parser.parse_args()  # 解析参数

        # 如果当前用户是 'pzy' 或者有权限修改其他用户密码
        if current_user.is_pzy():  # 检查当前用户是否为 pzy
            # 允许 'pzy' 修改任何用户的密码，需指定用户名
            parser.add_argument('username', type=str, required=False, help="Username")  # 添加用户名参数
            args = parser.parse_args()  # 解析参数
            if 'username' in request.json and request.json['username']:  # 检查用户名参数是否存在
                target_user = User.query.filter_by(username=request.json['username']).first()  # 获取目标用户
                if not target_user:  # 如果目标用户不存在
                    return {"message": "用户不存在"}, 404  # 返回用户不存在的消息
                target_user.set_password(args['new_password'])  # 设置目标用户的新密码
                db.session.commit()  # 提交当前会话
                return {"message": f"用户 '{target_user.username}' 的密码修改成功"}, 200  # 返回成功修改密码的消息
        else:  # 如果当前用户不是 pzy
            # 普通用户只能修改自己的密码
            current_user.set_password(args['new_password'])  # 设置当前用户的新密码
            db.session.commit()  # 提交当前会话
            return {"message": "密码修改成功"}, 200  # 返回修改成功的消息
